package com.fitcoders.inscripcion.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository("genericDAO")
@Transactional(readOnly = true)
public class GenericDAOImpl implements GenericDAO {

    @Autowired
    SessionFactory sessionFactory;

    /**
     * Guarda el Estado y podemos moficar mientras se encuentre en memoria
     *
     * @param model
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Serializable save(Object model) {
        return getSessionFactory().getCurrentSession().save(model);
    }
    
    @Transactional(readOnly = false)
    @Override
    public void saveList(List list) {
        Session ses = getSessionFactory().getCurrentSession();
        for (Object ob : list) {
            ses.save(ob);            
        }
    }
    
    @Transactional(readOnly = false)
    @Override
    public Serializable saveAnyId(Object model) {
        return getSessionFactory().getCurrentSession().save(model);
    }

    @Override
    public <T> T getById(Class<T> type, Integer id) {
        return (T) getSessionFactory().getCurrentSession().get(type, id);
    }

    @Override
    public <T> T getByHQL(String hql, Map<String, Object> parameters, Class<T> type) {
        Query que = getSessionFactory().getCurrentSession().createQuery(hql);
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                que.setParameter(entry.getKey(), entry.getValue());
            }
        }
        if (type != null) {
            que.setResultTransformer(Transformers.aliasToBean(type));
        }

        return (T) que.uniqueResult();
    }

    @Transactional(readOnly = false)
    @Override
    public <T> void delete(T t) {
        getSessionFactory().getCurrentSession().delete(t);
    }
    
    @Transactional(readOnly = false)
    @Override
    public void deleteCollecton(List t) {
        Session ses = getSessionFactory().getCurrentSession();
        for (Object t1 : t) {
            ses.delete(t1);
        }       
    }

    @Transactional(readOnly = false)
    @Override
    public void update(Object model) {
        getSessionFactory().getCurrentSession().update(model);
    }

    @Transactional(readOnly = false)
    @Override
    public void update(String query, boolean isSQL) {
        if (isSQL) {
            getSessionFactory().getCurrentSession().createSQLQuery(query).executeUpdate();
        } else {
            getSessionFactory().getCurrentSession().createQuery(query).executeUpdate();
        }
    }
    
    @Transactional(readOnly = false)
    @Override
    public <T> void saveOrUpdate(T t) {
        getSessionFactory().getCurrentSession().saveOrUpdate(t);
    }

    @Override
    public List listHQL(String hql, Map<String, Object> parameters, Class clazz) {
        Query query;
        if (clazz == null) {
            query = getSessionFactory().getCurrentSession().createQuery(hql);
        } else {
            query = getSessionFactory().getCurrentSession().createQuery(hql).setResultTransformer(Transformers.aliasToBean(clazz));
        }
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return query.list();
    }

    @Override
    public List listSQL(String sql, Map<String, Object> parameters, Class clazz) {
        Query query;
        if (clazz == null) {
            query = getSessionFactory().getCurrentSession().createSQLQuery(sql);
        } else {
            query = getSessionFactory().getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(clazz));
        }
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return query.list();
    }

    @Override
    public Object count(String query, Map<String, Object> parameters) {
        Query queryx = getSessionFactory().getCurrentSession().createQuery(query);
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                queryx.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return queryx.uniqueResult();

    }

    @Override
    public List listLazyHQL(String hql, Map<String, Object> parameters, int start, int finish, Class clazz) {
        Query query;
        if (clazz == null) {
            query = getSessionFactory().getCurrentSession().createQuery(hql);
        } else {
            query = getSessionFactory().getCurrentSession().createQuery(hql).setResultTransformer(Transformers.aliasToBean(clazz));
        }
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        query.setFirstResult(start)
                .setMaxResults(finish);
        return query.list();
    }
   
    
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

}
